package cn.wolfcode.service.impl;

import cn.wolfcode.common.exception.BusinessException;
import cn.wolfcode.domain.AccountLog;
import cn.wolfcode.domain.AccountTransaction;
import cn.wolfcode.domain.OperateIntergralVo;
import cn.wolfcode.mapper.AccountLogMapper;
import cn.wolfcode.mapper.AccountTransactionMapper;
import cn.wolfcode.mapper.UsableIntegralMapper;
import cn.wolfcode.service.IUsableIntegralService;
import cn.wolfcode.web.msg.IntergralCodeMsg;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.seata.rm.tcc.api.BusinessActionContext;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;


@Service
public class UsableIntegralServiceImpl implements IUsableIntegralService {
    @Autowired
    private UsableIntegralMapper usableIntegralMapper;
    @Autowired
    private AccountTransactionMapper accountTransactionMapper;
    @Autowired
    private AccountLogMapper accountLogMapper;

    @Override
    @Transactional
    public Boolean decrIntegral(OperateIntergralVo operateIntergralVo) {
        // 插入流水
        AccountLog accountLog = new AccountLog();
        accountLog.setPkValue(operateIntergralVo.getPk());
        Long value = operateIntergralVo.getValue();
        accountLog.setAmount(value);
        accountLog.setType(AccountLog.TYPE_DECR);
        accountLog.setInfo(operateIntergralVo.getInfo());
        accountLog.setGmtTime(new Date());
        accountLogMapper.insert(accountLog);
        // 减少积分
        int count = usableIntegralMapper.decrIntegral(operateIntergralVo.getUserId(), value);
        return count != 0;
    }

    @Override
    @Transactional
    public Boolean incrIntegral(OperateIntergralVo operateIntergralVo) {
        // 插入流水
        AccountLog accountLog = new AccountLog();
        accountLog.setPkValue(operateIntergralVo.getPk());
        Long value = operateIntergralVo.getValue();
        accountLog.setAmount(value);
        accountLog.setType(AccountLog.TYPE_INCR);
        accountLog.setInfo(operateIntergralVo.getInfo());
        accountLog.setGmtTime(new Date());
        accountLogMapper.insert(accountLog);
        // 增加积分
        int count = usableIntegralMapper.addIntergral(operateIntergralVo.getUserId(), value);
        return count != 0;
    }

    @Override
    @Transactional
    public Boolean incrIntergralTry(OperateIntergralVo operateIntergralVo, BusinessActionContext context) {
        // 退款业务try方法不用任何操作
        // 解决try方法未执行, cancel方法已执行, 通过插入一条数据来解决
        accountTransactionMapper.insert(createAccountTransaction(context, operateIntergralVo, AccountTransaction.INCR_TYPE, AccountTransaction.STATE_TRY));
        return true;
    }

    @Override
    @Transactional
    public Boolean incrIntergralCommit(BusinessActionContext context) {
        // 退款业务confirm方法增加积分
        String xid = context.getXid();
        String actionId = context.getBranchId() + "";
        AccountTransaction transaction = accountTransactionMapper.get(xid, actionId);
        if (transaction == null) {
            // 表明try没有执行  按照流程这是不可能的,所以抛出异常
            throw new BusinessException(IntergralCodeMsg.OP_INTERGRAL_ERROR);
        }
        int state = transaction.getState();
        if (AccountTransaction.STATE_TRY.equals(state)) {
            // 状态为初始化, 正常,执行增加积分业务
            OperateIntergralVo operateIntegralVo = getOperateIntegralVo(context);
            // 修改记录状态
            accountTransactionMapper.updateAccountTransactionState(xid, actionId, AccountTransaction.STATE_COMMIT, state);
            // 插入流水
            return incrIntegral(operateIntegralVo);
        } else if (AccountTransaction.STATE_COMMIT.equals(state)) {
            // 状态为已提交, 不做操作,解决幂等性
            return true;
        } else {
            throw new BusinessException(IntergralCodeMsg.OP_INTERGRAL_ERROR);
        }
    }

    @Override
    @Transactional
    public Boolean incrIntergralRollback(BusinessActionContext context) {
        // 退款业务cancel方法不用任何操作
        String xid = context.getXid();
        String actionId = context.getBranchId() + "";
        AccountTransaction transaction = accountTransactionMapper.get(xid, actionId);
        if (transaction == null) {
            // 表明try没有执行, 可能是try方法执行过慢,此时插入一条数据, 使try方法执行失败
            accountTransactionMapper.insert(createAccountTransaction(context, AccountTransaction.INCR_TYPE, AccountTransaction.STATE_CANCEL));
            return true;
        }
        int state = transaction.getState();
        if (AccountTransaction.STATE_TRY.equals(state)) {
            // 状态为初始化, 表明有try失败了, 执行cancel方法 但是增加积分cancel不用做任何操作
            accountTransactionMapper.updateAccountTransactionState(xid, actionId, AccountTransaction.STATE_CANCEL, state);
            return true;
        } else if(AccountTransaction.STATE_CANCEL.equals(state)) {
            // 状态为已回滚, 表明已执行, 所以不做操作, 解决幂等性问题
            return true;
        } else {
            throw new BusinessException(IntergralCodeMsg.OP_INTERGRAL_ERROR);
        }
    }


    @Override
    @Transactional
    public Boolean decrIntergralTry(OperateIntergralVo operateIntergralVo, BusinessActionContext context) {
        // 插入一条记录, 解决try方法未执行, cancel方法执行的问题
        accountTransactionMapper.insert(createAccountTransaction(context, operateIntergralVo, AccountTransaction.DECR_TYPE, AccountTransaction.STATE_TRY));
        // try方法 冻结积分
        int count = usableIntegralMapper.freezeIntergral(operateIntergralVo.getUserId(), operateIntergralVo.getValue());
        if (count != 0) {
            return true;
        } else {
            throw new BusinessException(IntergralCodeMsg.INTERGRAL_NOT_ENOUGH);
        }
    }

    @Override
    @Transactional
    public Boolean decrIntergralCommit(BusinessActionContext context) {
        String xid = context.getXid();
        String actionId = context.getBranchId() + "";
        AccountTransaction transaction = accountTransactionMapper.get(xid, actionId);
        if (transaction == null) {
            // 表明try没有执行  按照流程这是不可能的,所以抛出异常
            throw new BusinessException(IntergralCodeMsg.OP_INTERGRAL_ERROR);
        }
        int state = transaction.getState();
        if (AccountTransaction.STATE_TRY.equals(state)) {
            // 状态为初始化, 正常,执行增加积分业务
            OperateIntergralVo operateIntegralVo = getOperateIntegralVo(context);
            // 修改记录状态
            accountTransactionMapper.updateAccountTransactionState(xid, actionId, AccountTransaction.STATE_COMMIT, state);
            // confirm方法 减少积分,减少冻结积分
            Long userId = operateIntegralVo.getUserId();
            Long value = operateIntegralVo.getValue();
            int count = usableIntegralMapper.commitChange(userId, value);
            if (count != 0) {
                return true;
            } else {
                throw new BusinessException(IntergralCodeMsg.OP_INTERGRAL_ERROR);
            }
        } else if (AccountTransaction.STATE_COMMIT.equals(state)) {
            // 状态为已提交, 不做操作,解决幂等性
            return true;
        } else {
            throw new BusinessException(IntergralCodeMsg.OP_INTERGRAL_ERROR);
        }
    }

    @Override
    @Transactional
    public Boolean decrIntergralRollback(BusinessActionContext context) {
        String xid = context.getXid();
        String actionId = context.getBranchId() + "";
        AccountTransaction transaction = accountTransactionMapper.get(xid, actionId);
        if (transaction == null) {
            // 表明try没有执行, 可能是try方法执行过慢,此时插入一条数据, 使try方法执行失败
            accountTransactionMapper.insert(createAccountTransaction(context, AccountTransaction.DECR_TYPE, AccountTransaction.STATE_CANCEL));
            return true;
        }
        int state = transaction.getState();
        if (AccountTransaction.STATE_TRY.equals(state)) {
            OperateIntergralVo operateIntegralVo = getOperateIntegralVo(context);
            // 状态为初始化, 表明有try失败了
            accountTransactionMapper.updateAccountTransactionState(xid, actionId, AccountTransaction.STATE_CANCEL, state);
            // cancel方法, 减少冻结积分
            usableIntegralMapper.unFreezeIntergral(operateIntegralVo.getUserId(), operateIntegralVo.getValue());
            return true;
        } else if(AccountTransaction.STATE_CANCEL.equals(state)) {
            // 状态为已回滚, 表明已执行, 所以不做操作, 解决幂等性问题
            return true;
        } else {
            throw new BusinessException(IntergralCodeMsg.OP_INTERGRAL_ERROR);
        }
    }


    public AccountTransaction createAccountTransaction(BusinessActionContext context, String type, Integer state) {
        Object vo = context.getActionContext().get("operateIntergralVo");
        OperateIntergralVo operateIntegralVo = JSON.parseObject(vo.toString(), OperateIntergralVo.class);
        return createAccountTransaction(context,operateIntegralVo,type,state);
    }

    public AccountTransaction createAccountTransaction(BusinessActionContext context, OperateIntergralVo vo, String type, Integer state) {
        AccountTransaction transaction = new AccountTransaction();
        transaction.setTxId(context.getXid());
        transaction.setActionId(context.getBranchId() + "");
        transaction.setUserId(vo.getUserId());
        transaction.setGmtCreated(new Date());
        transaction.setAmount(vo.getValue());
        transaction.setType(type);
        transaction.setState(state);
        return transaction;
    }

    public OperateIntergralVo getOperateIntegralVo(BusinessActionContext context) {
        Object vo = context.getActionContext().get("operateIntergralVo");
        return JSON.parseObject(vo.toString(), OperateIntergralVo.class);
    }
}
